package com.rbac.admin.service.impl;

import com.rbac.admin.service.CacheService;
import com.rbac.admin.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 缓存服务实现类
 */
@Service
public class CacheServiceImpl implements CacheService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    @Override
    public void set(String key, Object value, long timeout) {
        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T get(String key) {
        return (T) redisTemplate.opsForValue().get(key);
    }

    @Override
    public void delete(String key) {
        redisTemplate.delete(key);
    }

    @Override
    public void deleteByPattern(String pattern) {
        Set<String> keys = redisTemplate.keys(pattern);
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
    }

    @Override
    public boolean hasKey(String key) {
        return Boolean.TRUE.equals(redisTemplate.hasKey(key));
    }

    @Override
    public long getExpire(String key) {
        Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
        return expire != null ? expire : -1;
    }

    @Override
    public void expire(String key, long timeout) {
        redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

    @Override
    public Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }
    
    @Override
    public void clearAll() {
        // 获取所有键
        Set<String> keys = redisTemplate.keys("*");
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
    }
    
    @Override
    public void clearUserCache(String username) {
        // 注意：这里不能直接注入SysUserService，会造成循环依赖
        // 所以我们直接使用模式匹配删除相关缓存
        
        // 删除用户信息缓存（模式匹配）
        deleteByPattern("user:*");
        
        // 删除用户token相关缓存（模式匹配）
        deleteByPattern("user:token:*");
        
        // 删除用户菜单和权限缓存（模式匹配）
        deleteByPattern("menu:user:*");
        deleteByPattern("permission:user:*");
    }
    
    @Override
    public void clearMenuCache() {
        // 删除所有菜单缓存
        deleteByPattern("menu:*");
    }
    
    @Override
    public void clearPermissionCache() {
        // 删除所有权限缓存
        deleteByPattern("permission:*");
    }
    
    @Override
    public Map<String, Object> getCacheStats() {
        Properties info = redisTemplate.execute((RedisCallback<Properties>) RedisServerCommands::info);
        Properties commandStats = redisTemplate.execute((RedisCallback<Properties>) connection -> 
                connection.info("commandstats"));
        
        Long dbSize = redisTemplate.execute(RedisServerCommands::dbSize);
        
        Map<String, Object> result = new HashMap<>(3);
        result.put("info", info);
        result.put("dbSize", dbSize);
        
        Map<String, Object> commandStatsMap = new HashMap<>();
        if (commandStats != null) {
            for (Object key : commandStats.keySet()) {
                String property = (String) key;
                String value = commandStats.getProperty(property);
                if (property.startsWith("cmdstat")) {
                    String command = property.substring(8);
                    commandStatsMap.put(command, value);
                }
            }
        }
        result.put("commandStats", commandStatsMap);
        
        // 获取各类缓存数量
        Map<String, Object> cacheCount = new HashMap<>(4);
        cacheCount.put("user", redisTemplate.keys("user:*").size());
        cacheCount.put("menu", redisTemplate.keys("menu:*").size());
        cacheCount.put("permission", redisTemplate.keys("permission:*").size());
        cacheCount.put("role", redisTemplate.keys("role:*").size());
        result.put("cacheCount", cacheCount);
        
        return result;
    }
}